//
//  LFXRuntime.m
//
//  Created by 米高 http://michaellfx.cnblogs.com on 3/6/15.
//  Copyright (c) 2015 米高. All rights reserved.
//

#import "LFXRuntime.h"
#import <objc/runtime.h>

void methodSwizNonThreadSafe(Class cls, SEL srcSelector, SEL dstSelector) {
    Method srcMethod = class_getClassMethod(cls, srcSelector);
    Method dstMethod = nil;
    if (srcMethod) {
        // class method
        dstMethod = class_getClassMethod(cls, dstSelector);
        if (!dstMethod) {
            return;
        }
    } else {
        // instance method
        srcMethod = class_getInstanceMethod(cls, srcSelector);
        if (srcMethod) {
            dstMethod = class_getInstanceMethod(cls, dstSelector);
            if (!dstMethod) {
                return;
            }
        }
    }
    // try add, if not, then exchange.
    if (class_addMethod(cls, srcSelector, method_getImplementation(dstMethod), method_getTypeEncoding(dstMethod))) {
        class_replaceMethod(cls, dstSelector, method_getImplementation(srcMethod), method_getTypeEncoding(srcMethod));
    } else {
        method_exchangeImplementations(srcMethod, dstMethod);
    }
    
}

static char *dispathOnceKey;

void methodSwizThreadSafe(Class cls, SEL srcSelector, SEL dstSelector) {
    NSNumber *dispatchOnceValue = objc_getAssociatedObject(cls, &dispathOnceKey);
    if (dispatchOnceValue.longValue) {
        return;
    }
    dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        methodSwizNonThreadSafe(cls, srcSelector, dstSelector);
    });
    objc_setAssociatedObject(cls, &dispathOnceKey, @(onceToken), OBJC_ASSOCIATION_RETAIN);
}
